package net.knightwatch.kwtools;

import java.util.ArrayList;

import net.knightwatch.kwtools.customers.Address;
import net.knightwatch.kwtools.customers.AddressAutoCompleteAdapter;
import net.knightwatch.kwtools.customers.Building;
import net.knightwatch.kwtools.database.KwToolsDatasource;
import android.app.Activity;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
/*
 * Activity used to create a new building for a customer object. The activity will be called from a customer
 * and pass the customer ID.
 * 
 * In the future this may be called directly so there will need to be a list to select the customer.
 */
public class BuildingActivity extends Activity implements LocationListener {
	private static final String TAG = "BuildingActivity";	
	private KwToolsDatasource datasource = new KwToolsDatasource(this);
	private Building building;
	private Address oldAddress;
	private EditText buildingName;
	private AutoCompleteTextView street;
	ArrayList<Address> customerAddresses;
	AddressAutoCompleteAdapter addressAdapter;
	private EditText city;
	private EditText state;
	private EditText zipcode;
	private EditText country;
	private TextView latitude;
	private TextView longitude;
	private LocationManager lm;
	private int noOfFixes = 0;



	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.building_activity_add);
		oldAddress = new Address();
		building = new Building();
		building.setCustomerId(getIntent().getLongExtra("customerId", -1));
		building.setId(getIntent().getLongExtra("buildingId", -1));
		setupWidgets();
		lm = (LocationManager)getSystemService(LOCATION_SERVICE);
		createStreetAddressAutoComplete();
		createBuildingNameEditText();
		createCityEditText();
		createStateEditText();
		createZipcodeEditText();
		createCountryEditText();
		// Check if a current building id is being passed to the activity for an update to the building.
		if(building.getId() > 0){
			// Load the building from the database to be edited. Async Task
			new GetBuildingTask().execute(building.getId());
		}
		// Get the current possible addresses that belong to a customer and display in a list.
	}
	private class GetBuildingTask extends AsyncTask<Long, Void, Void>{

		@Override
		protected Void doInBackground(Long... params) {
			// Lookup the building. Then fill in the details on the page.
			Log.d(TAG, "Looking Up building ID = "+building.getId());
			datasource.Open();			
			building = datasource.getBuilding(building.getId());
			datasource.Close();
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			// TODO Load the building to the GUI
			super.onPostExecute(result);
			oldAddress = building.getAddress();
			buildingName.setText(building.getName());
			street.setText(building.getAddress().getStreet());
			city.setText(building.getAddress().getCity());
			state.setText(building.getAddress().getState());
			zipcode.setText(building.getAddress().getZipcode());
			country.setText(building.getAddress().getCountry());
			latitude.setText(""+building.getpLatitude());
			longitude.setText(""+building.getpLongitude());			
		}

		@Override
		protected void onPreExecute() {
			// TODO Notify user what is going on.
			super.onPreExecute();
			Toast.makeText(BuildingActivity.this, "Please wait loading the building", Toast.LENGTH_LONG).show();
		}


	}
	private void createStreetAddressAutoComplete(){
		street = (AutoCompleteTextView)findViewById(R.id.street_etxt);
		customerAddresses = new ArrayList<Address>();
		addressAdapter = new AddressAutoCompleteAdapter(BuildingActivity.this, android.R.layout.simple_dropdown_item_1line, customerAddresses);
		street.setAdapter(addressAdapter);
		street.setThreshold(1);
		street.setOnItemClickListener(new OnItemClickListener(){

			public void onItemClick(AdapterView<?> adapter, View view,
					int index, long id) {
				updateAddress((Address) adapter.getItemAtPosition(index));
			}});
		// Text Watcher to change the value of the address
		street.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// change the value of the building object to reflect this value\
				building.getAddress().setStreet(s.toString());				
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// not used

			}

		});

	}

	protected void updateAddress(Address address) {
		// TODO Update address view
		building.setAddress(address);
		street.setText(building.getAddress().getStreet());
		city.setText(building.getAddress().getCity());
		state.setText(building.getAddress().getState());
		zipcode.setText(building.getAddress().getZipcode());
		country.setText(building.getAddress().getCountry());
	}
	private void setupWidgets() {

		this.latitude = (TextView)findViewById(R.id.latitude_txt);
		this.latitude.setText("Waiting");

		this.longitude = (TextView)findViewById(R.id.longitude_txt);
		this.longitude.setText("Waiting");
	}
	private void createCountryEditText() {
		country = (EditText)findViewById(R.id.address_country_etxt);
		country.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// Change the value of the building object
				building.getAddress().setCountry(s.toString());

			}

			public void beforeTextChanged(CharSequence arg0, int arg1,
					int arg2, int arg3) {
				// not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// not used

			}

		});
		country.setText("USA");
	}
	private void createZipcodeEditText() {
		zipcode = (EditText)findViewById(R.id.address_zipcode_etxt);
		zipcode.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// Update the value of the address in the building object
				building.getAddress().setZipcode(s.toString());

			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// Not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// Not used

			}

		});
	}
	private void createStateEditText() {
		state = (EditText)findViewById(R.id.address_state_etxt);
		state.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// Update the address object on the building object. 
				building.getAddress().setState(s.toString());

			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// Not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// Not used

			}

		});
		state.setText("MI");
	}
	private void createCityEditText() {
		city = (EditText)findViewById(R.id.address_city_etxt);
		city.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// update the building address object city
				building.getAddress().setCity(s.toString());

			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// not used

			}

		});
	}
	private void createBuildingNameEditText() {
		buildingName = (EditText)findViewById(R.id.BuilldingName_etxt);
		buildingName.addTextChangedListener(new TextWatcher(){

			public void afterTextChanged(Editable s) {
				// update the name of the building object
				building.setName(s.toString());
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				// not used

			}

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
				// not used

			}

		});
	}
	private class LookupCustomerAddressesTask extends AsyncTask<Long, Void, Void> {

		@Override
		protected Void doInBackground(Long... params) {
			// Look up the customers addresses
			long customerId = (Long) params[0];
			try{
				Log.d(TAG, "Looking up the addresses for a customer.");
				datasource.Open();
				customerAddresses.clear();
				for(Address a : datasource.getCustomerAddresses(customerId)){
					// Add the address to the list.
					customerAddresses.add(a);
				}
			} catch (Exception e){
				Log.e(TAG, "Unable to retrieve addresses for the current customer");
			} finally {
				datasource.Close();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			// Notify the adapter of the change.
			super.onPostExecute(result);
			Log.v(TAG, "Notifying addressAdapter of dataset change");
			addressAdapter.notifyDataSetChanged();
		}


	}

	/* Request updates at startup */
	@Override
	protected void onResume() {
		lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10f, this);
		super.onResume();
		// Lookup the autocomplete addresses for this activity
		new LookupCustomerAddressesTask().execute(building.getCustomerId());
	}

	/* Remove the locationlistener updates when Activity is paused */
	@Override
	protected void onPause() {
		lm.removeUpdates(this);
		super.onPause();			
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.building_add_menu, menu);
		super.onCreateOptionsMenu(menu);
		return true;
	}
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Log.i(TAG, "A button was pressed");
		switch (item.getItemId()) {
		case R.id.saveBuilding:
			SaveBuildingToCustomer();
			return true;
		case R.id.cancelBuilding:
			this.finish();
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}
	private void SaveBuildingToCustomer(){
		// FIXME Save building when it is new ID = 0. Update to newly selected building when ID Changes.
		if(!oldAddress.equals(building.getAddress())){
			if(building.getAddress().getAddressId() > 0){
				Log.d(TAG, "Updating the building to the new address ID");
			} else {
				Log.d(TAG, "Old Address Equals the New Address not creating a new address in the database.");
				building.getAddress().setAddressId(0);
			}
		}
		try {
			datasource.Open();
			if(building.getId() > 0){
				// TODO Update the building information
				datasource.updateBuilding(building);
				Log.v(TAG, "Updated the building in the database");
			} else {
				// Add a new building to the customer in the database
				building = datasource.createBuilding(building);
				Log.v(TAG, "New Building was saved to the database");
			}
		} catch (Exception e){
			e.printStackTrace();
			Log.e(TAG, "Unable to save the building to the database");
		} finally { 
			datasource.Close();
		}
		this.finish();
	}

	public void onLocationChanged(Location location) {
		// BuildingActivity onLocationChanged method stub
		Log.v(TAG, "Location has Changed");
		noOfFixes++;
		Log.v(TAG, "Number of Fixes = "+noOfFixes);
		building.setpLatitude(location.getLatitude());
		building.setpLongitude(location.getLongitude());
		building.setpAltitude(location.getAltitude());
		building.setpAccuracy(location.getAccuracy());
		building.setpTime(location.getTime());
		latitude.setText(Double.toString(building.getpLatitude()));
		longitude.setText(Double.toString(building.getpLongitude()));

	}
	public void onProviderDisabled(String provider) {
		// BuildingActivity onProviderDisabeld method stub
		Log.v(TAG, "Location Provider is Disabled");
		/* Bring up the GPS settings for the device	 */
		Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		startActivity(intent);			
	}
	public void onProviderEnabled(String provider) {
		// BuildingActivity onProviderEnabled method stub
		Log.v(TAG, "Location Provider is Enabled");
		Toast.makeText(this, "Using GPS to Obtain Building Location", Toast.LENGTH_LONG).show();
	}
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// BuildingActivity onStatusChagned
		String message = null;
		message += ("Status Has Changed:");
		switch(status){
		case LocationProvider.OUT_OF_SERVICE:
			message += (" Out of Service");
			LogAndNotifiy(message);
			break;
		case LocationProvider.TEMPORARILY_UNAVAILABLE:
			message += (" Temporarily Unavailable");
			LogAndNotifiy(message);
			break;
		case LocationProvider.AVAILABLE:
			message += (" Available");
			LogAndNotifiy(message);
			break;
		}

	}
	@Override
	protected void onStop(){
		finish();
		super.onStop();
	}
	private void LogAndNotifiy(String sb) {
		// build message notify and send to log
		String message;
		message = sb.toString();
		Log.v(TAG, message);
		Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
	}
}
